part of "../factory.dart";

/// 源于植学启原礼盒包装纸的计算
/// 假设物体为长方体，计算它所需要的最小面积包装纸（正方形）
///
/// 思路：
/// 包装纸与物体以45度角居中摆放，用物体的长或宽（结合高度之后）除以根号2，就是对应包装纸的边长部分（称为影子）
/// 长影子 = (长 + 高 × 2) / 2 ^ 0.5
/// 宽影子 = (宽 + 高 × 2) / 2 ^ 0.5
/// 重叠部分 = 高 × 2 ^ 0.5
/// 边长 = (长影子 + 宽影子 - 重叠部分) * (1 + 出血比例)
///
/// 注：
/// 1. 由于包装纸不可能刚好，所以需要出血用于容忍误差（为原来的1/10）
/// 2. 默认单位为mm
int wrapPaperEdge(double x, double y, double z) {
  assert(x > 0 && y > 0 && z > 0, "输入必须大于0");

  // 1. 确定谁是长宽高
  // 将输入排序
  List<double> dimensions = [x, y, z];
  dimensions.sort((a, b) => b.compareTo(a));

  // 按排序赋值给长、宽、高
  double length = dimensions[0];
  double width = dimensions[1];
  double height = dimensions[2];

  // 2. 分别计算影子
  double longShadow = (length + height * 2) / sqrt(2);
  double shortShadow = (width + height * 2) / sqrt(2);
  double overlap = height * sqrt(2);

  // 3. 计算总边长
  const double bleedRatio = 0.1;
  double edge = (longShadow + shortShadow - overlap) * (1 + bleedRatio);

  // 4. 以10为单位，向上取整，并返回结果
  int roundUpToTen = (edge ~/ 10 + 1) * 10;
  return roundUpToTen;
}

/// 直接运行的话，输入各项参数即可
void main(List<String> args) {
  // 1. 确保输入正确
  assert(args.length >= 3, "必须提供长宽高");

  // 2. 将输入转换为double
  double x = double.parse(args[0]);
  double y = double.parse(args[1]);
  double z = double.parse(args[2]);

  // 3. 运行程序并print结果
  final edge = wrapPaperEdge(x, y, z);
  print("包装纸最小边长为$edge毫米");
}
